# #######################
# IMPORTS AND BASIC SETUP
# #######################

import unittest
import sys
import os.path


# Change the following line to reflect wherever your
# app engine installation and the mocker library are
APPENGINE_PATH = '../google/appengine'
MOCKER_PATH = '../mocker'


# Add app-engine related libraries to your path
paths = [
    APPENGINE_PATH,
    MOCKER_PATH,
]
for path in paths:
  if not os.path.exists(path): 
    raise 'Path does not exist: %s' % path
sys.path = paths + sys.path



# ###############
# TEST DEFINITION
# ###############

import mocker
import handler
import model


class UnitTests(mocker.MockerTestCase):
  """Unit tests for the MainPage and GuestBook handler."""

  def setUp(self):
    self.request = self.mocker.mock()
    self.response = self.mocker.mock()
    self.handler1 = testy.InfluenceViewScore()
    self.handler2 = testy.DeathViewScore()
    self.handler3 = testy.InfluenceTurnIn()
    self.handler4 = testy.DeathTurnIn()
   
    self.handler1.request = self.request
    self.handler1.response = self.response
    self.handler2.request = self.request
    self.handler2.response = self.response
    self.handler3.request = self.request
    self.handler3.response = self.response
    self.handler4.request = self.request
    self.handler4.response = self.response
    
    self.InfluenceGrade = self.mocker.replace('testy.InfluenceGrade')
    self.DeathGrade = self.mocker.replace('testy.DeathGrade')
    self.users = self.mocker.replace('google.appengine.api.users')
    self.template = self.mocker.replace('google.appengine.ext.webapp.template')

  def testInfluenceGradeGetWhenLoggedIn(self):
    # What should happen in a regular request?
    # First, we create a query on all grades
    all_query = self.mocker.mock()
    self.InfluenceGrade.all()
    self.mocker.result(all_query)
    ordered_query = self.mocker.mock()
    all_query.order('-date')
    self.mocker.result(ordered_query)
    ordered_query.fetch(10)
    self.mocker.result('Query result for template')
    
    # We are currently logged into a fake user, 
    # thus a logout-url is created
    fake_user = self.mocker.mock()
    self.users.get_current_user()
    self.mocker.result(fake_user)
    self.request.uri
    self.mocker.result('fake uri')
    self.users.create_logout_url('fake uri')
    self.mocker.result('fake logout uri')
    
    # With that data, rendering will be invoked
    out = self.mocker.mock()
    self.response.out
    self.mocker.result(out)
    self.template.render(mocker.ANY, mocker.ANY)
    def checkArgs(path, params):
        template_values = {
          'grades': latest_grades,
          'totalscore': totalscore,
          'totalitems': totalitems,
          'percentage': percentage,
          'url': login_url(self.request.uri),
          'url_linktext': login_text(), }
        
        self.assert_(path.endswith('influence_score.html'))
        self.assertEqual(template_values, params)
        return '<html/>'
    self.mocker.call(checkArgs)
    out.write('<html/>')
    
    self.mocker.replay()
    self.handler1.get()
    
  def testInfluenceGradeGetWhenLoggedOut(self):
    # What should happen in a regular request?
    # First, we create a query on all grades
    all_query = self.mocker.mock()
    self.InfluenceGrade.all()
    self.mocker.result(all_query)
    ordered_query = self.mocker.mock()
    all_query.order('-date')
    self.mocker.result(ordered_query)
    ordered_query.fetch(10)
    self.mocker.result('Query result for template')
    
    # We are currently logged into a fake user, 
    # thus a login-url is created
    fake_user = self.mocker.mock()
    self.users.get_current_user()
    self.mocker.result(None)
    self.request.uri
    self.mocker.result('fake uri')
    self.users.create_login_url('fake uri')
    self.mocker.result('fake login uri')
    
    # With that data, rendering will be invoked
    out = self.mocker.mock()
    self.response.out
    self.mocker.result(out)
    self.template.render(mocker.ANY, mocker.ANY)
    def checkArgs(path, params):
        template_values = {
          'grades': latest_grades,
          'totalscore': totalscore,
          'totalitems': totalitems,
          'percentage': percentage,
          'url': login_url(self.request.uri),
          'url_linktext': login_text(), }
        self.assert_(path.endswith('influence_score.html'))
        self.assertEqual(template_values, params)
        return '<html/>'
    self.mocker.call(checkArgs)
    out.write('<html/>')
      
    self.mocker.replay()
    self.handler1.get()
    

def testDeathGradeGetWhenLoggedIn(self):
    # What should happen in a regular request?
    # First, we create a query on all grades
    all_query = self.mocker.mock()
    self.DeathGrade.all()
    self.mocker.result(all_query)
    ordered_query = self.mocker.mock()
    all_query.order('-date')
    self.mocker.result(ordered_query)
    ordered_query.fetch(10)
    self.mocker.result('Query result for template')
    
    # We are currently logged into a fake user, 
    # thus a logout-url is created
    fake_user = self.mocker.mock()
    self.users.get_current_user()
    self.mocker.result(fake_user)
    self.request.uri
    self.mocker.result('fake uri')
    self.users.create_logout_url('fake uri')
    self.mocker.result('fake logout uri')
    
    # With that data, rendering will be invoked
    out = self.mocker.mock()
    self.response.out
    self.mocker.result(out)
    self.template.render(mocker.ANY, mocker.ANY)
    def checkArgs(path, params):
        template_values = {
          'grades': latest_grades,
          'totalscore': totalscore,
          'totalitems': totalitems,
          'percentage': percentage,
          'url': login_url(self.request.uri),
          'url_linktext': login_text(), }

        self.assert_(path.endswith('death_score.html'))
        self.assertEqual(template_values, params)
      
        return '<html/>'
    self.mocker.call(checkArgs)
    out.write('<html/>')
    
    self.mocker.replay()
    self.handler2.get()
    
def testDeathGradeGetWhenLoggedOut(self):
    # What should happen in a regular request?
    # First, we create a query on all grades
    all_query = self.mocker.mock()
    self.DeathGrade.all()
    self.mocker.result(all_query)
    ordered_query = self.mocker.mock()
    all_query.order('-date')
    self.mocker.result(ordered_query)
    ordered_query.fetch(10)
    self.mocker.result('Query result for template')
    
    # We are currently logged into a fake user, 
    # thus a login-url is created
    fake_user = self.mocker.mock()
    self.users.get_current_user()
    self.mocker.result(None)
    self.request.uri
    self.mocker.result('fake uri')
    self.users.create_login_url('fake uri')
    self.mocker.result('fake login uri')
    
    # With that data, rendering will be invoked
    out = self.mocker.mock()
    self.response.out
    self.mocker.result(out)
    self.template.render(mocker.ANY, mocker.ANY)
    def checkArgs(path, params):
        template_values = {
          'grades': latest_grades,
          'totalscore': totalscore,
          'totalitems': totalitems,
          'percentage': percentage,
          'url': login_url(self.request.uri),
          'url_linktext': login_text(), }
        self.assert_(path.endswith('death_score.html'))
        self.assertEqual(template_values, params)
        return '<html/>'
    self.mocker.call(checkArgs)
    out.write('<html/>')
      
    self.mocker.replay()
    self.handler2.get()
    

def testInfluenceTurnInWhenLoggedIn(self):
    # First, a new grade is created
    grade = self.mocker.mock()
    self.InfluenceGrade()
    self.mocker.result(grade)
    
    # The user is fetched and assigned to the grade
    fake_user = self.mocker.mock()
    self.users.get_current_user()
    self.mocker.count(2)
    self.mocker.result(fake_user)
    grade.author = fake_user
    
    # Next, the content is fetched from a request parameter
    self.request.get('content')
    self.mocker.result('mock content')
    grade.content = 'mock content'
    
    # Last but not least, store the post and redirect
    grade.put()
    self.handler3.redirect = lambda x: self.assertEquals('/taught', x)
    
    # Everything is recorded, so let's go into replay mode :-)
    self.mocker.replay()
    self.handler3.post()
    
def testInfluenceTurnInWhenLoggedOut(self):
    handler3 = self.mocker.mock(testy.InfluenceTurnIn)
    handler3.request
    self.mocker.count(0,10)
    self.mocker.result(self.request)
    handler3.response
    self.mocker.count(0,10)
    self.mocker.result(self.response)
    
    # First, a new grade is created
    grade = self.mocker.mock()
    self.InfluenceGrade()
    self.mocker.result(grade)
    
    # The user is None and thus not assigned to the grade
    self.users.get_current_user()
    self.mocker.result(None)
    
    # Next, the content is fetched from a request parameter
    self.request.get('content')
    self.mocker.result('mock content')
    grade.content = 'mock content'
    
    # Last but not least, store the post and redirect
    # TODO: (check blog post for more information)
    grade.put()
    mock_redirect = self.mocker.mock()
    handler3.redirect('/taught')
    
    self.mocker.replay()
    testy.InfluenceTurnIn.post(handler3)


def testDeathTurnInWhenLoggedIn(self):
    # First, a new grade is created
    grade = self.mocker.mock()
    self.DeathGrade()
    self.mocker.result(grade)
    
    # The user is fetched and assigned to the grade
    fake_user = self.mocker.mock()
    self.users.get_current_user()
    self.mocker.count(2)
    self.mocker.result(fake_user)
    grade.author = fake_user
    
    # Next, the content is fetched from a request parameter
    self.request.get('content')
    self.mocker.result('mock content')
    grade.content = 'mock content'
    
    # Last but not least, store the post and redirect
    grade.put()
    self.handler4.redirect = lambda x: self.assertEquals('/shot', x)
    
    # Everything is recorded, so let's go into replay mode :-)
    self.mocker.replay()
    self.handler4.post()
    
def testDeathTurnInWhenLoggedOut(self):
    handler4 = self.mocker.mock(testy.DeathTurnIn)
    handler4.request
    self.mocker.count(0,10)
    self.mocker.result(self.request)
    handler3.response
    self.mocker.count(0,10)
    self.mocker.result(self.response)
    
    # First, a new grade is created
    grade = self.mocker.mock()
    self.DeathGrade()
    self.mocker.result(grade)
    
    # The user is None and thus not assigned to the grade
    self.users.get_current_user()
    self.mocker.result(None)
    
    # Next, the content is fetched from a request parameter
    self.request.get('content')
    self.mocker.result('mock content')
    grade.content = 'mock content'
    
    grade.put()
    mock_redirect = self.mocker.mock()
    handler4.redirect('/shot')
    
    self.mocker.replay()
    testy.InfluenceTurnIn.post(handler4)
    

# #####################
# LAUNCH UNIT TESTS
# #####################


if __name__ == "__main__":
  unittest.main()
